package com.joysuch.wwyt.quartz.bp;

import cn.hutool.core.collection.CollectionUtil;
import com.joysuch.wwyt.bp.bean.BpBaseUserBean;
import com.joysuch.wwyt.bp.constant.AppNotifyContentPre;
import com.joysuch.wwyt.bp.entity.BpCommonNotifyRel;
import com.joysuch.wwyt.bp.entity.BpEmergencyContingencyPlans;
import com.joysuch.wwyt.bp.entity.BpEmergencyExercisePlan;
import com.joysuch.wwyt.bp.enums.CommonNotifyRelType;
import com.joysuch.wwyt.bp.repository.BpEmergencyContingencyPlansDao;
import com.joysuch.wwyt.bp.repository.BpEmergencyExercisePlanDao;
import com.joysuch.wwyt.bp.service.BpCommonNotifyRelService;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.common.entity.CommonBusinessNotice;
import com.joysuch.wwyt.common.entity.CommonIndexNotify;
import com.joysuch.wwyt.common.enums.AppBusinessNoticeTypes;
import com.joysuch.wwyt.common.enums.CommonIndexNotifyTypes;
import com.joysuch.wwyt.common.repository.CommonIndexNotifyDao;
import com.joysuch.wwyt.common.service.CommonBusinessNoticeService;
import com.joysuch.wwyt.common.service.CommonIndexNotifyService;
import com.joysuch.wwyt.core.common.util.DateTimeUtil;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.repository.BaseConfigDao;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Component
public class EmergencyDrillSchedule {

    @Autowired
    private BaseConfigDao baseConfigDao;
    @Autowired
    private BpCommonNotifyRelService commonNotifyRelService;
    @Autowired
    private CommonIndexNotifyDao commonIndexNotifyDao;
    @Autowired
    private CommonBusinessNoticeService commonBusinessNoticeService;
    @Autowired
    private BpEmergencyContingencyPlansDao bpEmergencyContingencyPlansDao;
    @Autowired
    private BaseUserDao baseUserDao;
    @Autowired
    private CommonIndexNotifyService commonIndexNotifyService;
    @Autowired
    private BpEmergencyExercisePlanDao bpEmergencyExercisePlanDao;

    // @Scheduled(cron = "0 10 0 * * ?")
    // @Scheduled(fixedDelay = 60000, initialDelay = 10000L)
    public void checkExpired() {
        try {
            doTask();
        } catch (Exception e) {
            log.error("do task error", e);
        }
    }

    private void doTask() {
        BaseConfig config = baseConfigDao.findFirstByCodeNative("yingji.xiaofang.notice.day");
        if (config == null || StringUtils.isEmpty(config.getValue())) {
            log.info("not found yingji.xiaofang.notice.day config");
            return;
        }
        int days = Integer.parseInt(config.getValue().trim());

        String formatDate = DateTimeUtil.formatDate(new Date());
        Date date = DateTimeUtil.parseDateV2(formatDate);
        long t = date.getTime() - days * 24L * 3600 * 1000;
        Date startDate = new Date(t);
        Date endDate = new Date(date.getTime() - (days - 1) * 24L * 3600 * 1000);

        List<BpEmergencyExercisePlan> plans = bpEmergencyExercisePlanDao.findExpired(startDate, endDate);
        if (CollectionUtil.isEmpty(plans)) {
            return;
        }

        List<Long> planIds = plans.stream().map(BpEmergencyExercisePlan::getId).collect(Collectors.toList());
        final Map<Long, Integer> countMap = commonNotifyRelService.countMapByRelAndType(planIds, CommonNotifyRelType.emergency_training);
        // count数大于零的，不处理
        plans = plans.stream().filter(p -> {
            Integer count = countMap.get(p.getId());
            return Objects.isNull(count) || count <= 0;
        }).collect(Collectors.toList());

        if (CollectionUtil.isEmpty(plans)) {
            return;
        }
        Set<Long> emergencyContingencyIds = plans.stream().map(BpEmergencyExercisePlan::getPid).collect(Collectors.toSet());
        List<BpEmergencyContingencyPlans> allContingency = bpEmergencyContingencyPlansDao.findAllById(emergencyContingencyIds);
        if (CollectionUtil.isEmpty(allContingency)) {
            return;
        }
        Map<Long, BpEmergencyContingencyPlans> contingencyMap = allContingency.stream().collect(Collectors.toMap(BpEmergencyContingencyPlans::getId, Function.identity()));
        Map<Long, BpBaseUserBean> userMap = buildAllUserInfo(allContingency);

        List<BpCommonNotifyRel> commonNotifyRels = new ArrayList<>();
        List<CommonIndexNotify> notifyList = Lists.newArrayList();
        List<CommonBusinessNotice> commonBusinessNotices = Lists.newArrayList();

        Date now = new Date();
        for (BpEmergencyExercisePlan plan : plans) {

            notice(plan, days, userMap, contingencyMap, notifyList, commonBusinessNotices);

            BpCommonNotifyRel bpCommonNotifyRel = new BpCommonNotifyRel();
            bpCommonNotifyRel.setRelId(plan.getId());
            bpCommonNotifyRel.setType(CommonNotifyRelType.emergency_training.getCode());
            bpCommonNotifyRel.setOrgCode("001-001");
            bpCommonNotifyRel.setTenentId(1L);
            bpCommonNotifyRel.setCreateBy(9784L);
            bpCommonNotifyRel.setUpdateBy(9784L);

            bpCommonNotifyRel.setCreateTime(now);
            bpCommonNotifyRel.setUpdateTime(now);
            bpCommonNotifyRel.setDeleteFlag("0");

            commonNotifyRels.add(bpCommonNotifyRel);
        }
        if (CollectionUtil.isNotEmpty(commonNotifyRels)) {
            commonNotifyRelService.saveBatch(commonNotifyRels);
        }
        if (CollectionUtil.isNotEmpty(notifyList)) {
            commonIndexNotifyDao.saveAll(notifyList);
        }
        if (CollectionUtil.isNotEmpty(commonBusinessNotices)) {
            commonBusinessNoticeService.saveBatch(commonBusinessNotices);
        }
    }

    private void notice(BpEmergencyExercisePlan plan, int days, Map<Long, BpBaseUserBean> userMap,
                        Map<Long, BpEmergencyContingencyPlans> contingencyMap, List<CommonIndexNotify> notifyList,
                        List<CommonBusinessNotice> commonBusinessNotices) {

        BpEmergencyContingencyPlans bpEmergencyContingencyPlan = contingencyMap.get(plan.getPid());
        if (Objects.isNull(bpEmergencyContingencyPlan)) {
            return;
        }
        String emergencyMembers = bpEmergencyContingencyPlan.getEmergencyMember();

        List<BpBaseUserBean> useDeparemergencyMembersts = new ArrayList<>();
        if (!StringUtils.isEmpty(emergencyMembers)) {
            String[] eString = emergencyMembers.split(",");
            for (int j = 0; j < eString.length; j++) {
                BpBaseUserBean user = userMap.get(Long.valueOf(eString[j].trim()));
                if (Objects.nonNull(user)) {
                    useDeparemergencyMembersts.add(user);
                }
            }
        }
        Date now = new Date();
        for (BpBaseUserBean baseUser : useDeparemergencyMembersts) {
            //提醒逻辑更改为证书提醒时间加上提前量后的提醒时间在当前时间之前的需要发送提醒消息,
            //为了防止重复生成提醒消息,以cert_user_id,和提醒时间以及提醒人员id,以及证书管理的类型(到期，复证),以及证书的过期日期为条件去查重,符合条件的不去生成通知
            CommonIndexNotify notify = new CommonIndexNotify();
            //因为是定时任务生成的通知，兼容提前量大于剩余时间的数据，提醒时间统一取当前时间
//            notify.setBusinessDate();
            //到期提醒日期
            notify.setRemindDate(LocalDate.now());
            //到期提醒时间
            notify.setRemindDateTime(LocalDateTime.now());


            notify.setType(CommonIndexNotifyTypes.URGENT_PLAN.getType());
            notify.setReadFlag(0);
            notify.setQueueOrNot(0);
            notify.setRemindedOrNot(0);
            //应急预案id
            notify.setEduCertUserId(bpEmergencyContingencyPlan.getId());
            //到期提醒日期
            notify.setRemindDate(LocalDate.now());
            //到期提醒时间
            notify.setRemindDateTime(LocalDateTime.now());
            //人员id
            notify.setUserId(baseUser.getId());
            //提醒message格式：人+证书+日期+即将过期
            String message = baseUser.getName() + ",应急演练计划:" + bpEmergencyContingencyPlan.getName()
                    + "(" + bpEmergencyContingencyPlan.getCode() + ")还有" + days + "天即将开始";


            notify.setTenentId(bpEmergencyContingencyPlan.getTenentId());
            notify.setOrgCode(bpEmergencyContingencyPlan.getOrgCode());
            notify.setCreateBy(null);
            notify.setUpdateBy(null);
            notify.setReadFlag(0);
            notify.setQueueOrNot(1);
            notify.setRemindedOrNot(1);
//            notify.setRecordId(baseUser.getId());
            notify.setNotifyMessage(message);

            notifyList.add(notify);

            CommonBusinessNotice notice = new CommonBusinessNotice();
            notice.setNoticeTitle(AppNotifyContentPre.TASK_NOTIFY);
            notice.setBusinessType(AppBusinessNoticeTypes.EMERGENCY_DRILL_PLAN.getType());
            notice.setNoticeContent(message);
            notice.setNoticeUser(baseUser.getId());
            notice.setReaded("0");
            notice.setRefId(bpEmergencyContingencyPlan.getId());
            notice.setSendTime(new Date());

            notice.setTenentId(1L);
            notice.setCreateBy(9784L);
            notice.setUpdateBy(9784L);

            notice.setCreateTime(now);
            notice.setUpdateTime(now);
            notice.setDeleteFlag("0");

            commonBusinessNotices.add(notice);
        }
    }

    public Map<Long, BpBaseUserBean> buildAllUserInfo(List<BpEmergencyContingencyPlans> allContingency) {
        Set<Long> allUserIds = new HashSet<>();
        for (BpEmergencyContingencyPlans contingency : allContingency) {
            String emergencyMember = contingency.getEmergencyMember();
            if (!StringUtils.isEmpty(emergencyMember)) {
                List<String> userIdStr = Arrays.asList(emergencyMember.split(Constant.SPLIT_COMMA));
                if (CollectionUtil.isEmpty(userIdStr)) {
                    continue;
                }
                Set<Long> currentUserIds = userIdStr.stream().map(Long::valueOf).collect(Collectors.toSet());
                allUserIds.addAll(currentUserIds);
            }
        }
        if (CollectionUtil.isEmpty(allUserIds)) {
            return Collections.emptyMap();
        }
        List<BaseUser> allUser = baseUserDao.getUsersByIds(new ArrayList<>(allUserIds));
        if (CollectionUtil.isEmpty(allUser)) {
            return Collections.emptyMap();
        }
        return allUser.stream().map(u -> {
            BpBaseUserBean bpBaseUserBean = new BpBaseUserBean();
            bpBaseUserBean.setId(u.getId());
            bpBaseUserBean.setName(u.getRealName());
            return bpBaseUserBean;
        }).collect(Collectors.toMap(BpBaseUserBean::getId, Function.identity()));
    }

}
